package com.example.chatroom.controller;

import com.example.chatroom.common.ApplicationVariable;
import com.example.chatroom.component.OnlineUserManager;
import com.example.chatroom.entity.*;
import com.example.chatroom.service.MessageService;
import com.example.chatroom.service.MessageSessionService;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.io.IOException;
import java.util.List;

@Component
public class WebSocketAPI extends TextWebSocketHandler {
    @Autowired
    private OnlineUserManager onlineUserManager;

    private ObjectMapper objectMapper = new ObjectMapper();

    @Autowired
    private MessageSessionService messageSessionService;

    @Autowired
    private MessageService messageService;

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        System.out.println("[WebSocketAPI] 连接成功！");
        // session.getAttributes()得到的是一组Map数据，可通过get方法获取到用户user
        UserEntity user = (UserEntity) session.getAttributes().get(ApplicationVariable.SESSION_USER_KEY);
        // System.out.println(session.getAttributes().toString());
        if(user == null) return;
        System.out.println("获取到的userId:" + user.getUser_id());
        // 把这个webSocketSession存储于HashMap
        onlineUserManager.online(user.getUser_id(), session);
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        System.out.println("[WebSocketAPI] 收到消息！" + message.toString());
        // TODO: 后续的消息接收,转发,以及保存等操作的处理
        // 1.获取到当前用户的信息
        UserEntity user = (UserEntity) session.getAttributes().get(ApplicationVariable.SESSION_USER_KEY);
        // 2.针对请求进行解析,把Json格式字符串转化为Json对象
        MessageRequest request = objectMapper.readValue(message.getPayload(), MessageRequest.class);
        if(request.getType().equals("message")){
            // 进行消息转发
            transferMessage(user,request);
        }else{
            System.out.println("[WebSocketAPI] req.type 有误! " + message.getPayload());
        }

    }

    // 通过这个方法来完成消息实际的转发工作.
    // 第一个参数就表示这个要转发的消息, 是从谁那来的.
    private void transferMessage(UserEntity fromUser, MessageRequest request) throws IOException {
        // 1. 构造一个待转发的响应对象. MessageResponse
        MessageResponse response = new MessageResponse();
        response.setType("message");
        response.setFromId(fromUser.getUser_id());
        response.setFromName(fromUser.getUsername());
        response.setSessionId(request.getSessionId());
        response.setContent(request.getContent());

        // 将 Java对象转换成Json字符串
        String respJson = objectMapper.writeValueAsString(response);
        System.out.println("[transferMessage] respJson: " + respJson);
        // 2. 根据请求中的sessionId, 获取到这个 MessageSession 里都有哪些用户. 通过查询数据库就能够知道了
        List<FriendEntity> friends = messageSessionService.getFriendsBySessionId(request.getSessionId(), fromUser.getUser_id());
        FriendEntity myself = new FriendEntity();
        myself.setFriendId(fromUser.getUser_id());
        myself.setFriendName(fromUser.getUsername());
        friends.add(myself);

        // 3. 循环遍历上述的这个列表, 给列表中的每个用户都发一份响应消息
        // 注意: 这里除了给查询到的好友们发, 也要给自己也发一个. 方便实现在自己的客户端上显示自己发送的消息.
        for (FriendEntity friend: friends) {
            // 根据每个用户的 userId, 进一步的查询刚才准备好的 OnlineUserManager, 得到对应的 WebSocketSession 从而进行发送消息
            WebSocketSession webSocketSession = onlineUserManager.getWebSocketSession(friend.getFriendId());
            if(webSocketSession == null){
                // 该用户不在线，不发送消息
                continue;
            }
            // 该用户不在线，发送消息
            webSocketSession.sendMessage(new TextMessage(respJson));
        }

        // 4. 转发的消息, 还需要添加到数据库里. 后续用户如果下线之后, 重新上线, 还可以通过历史消息的方式获取到之前的消息.
        MessageEntity message = new MessageEntity();
        message.setFromId(fromUser.getUser_id());
        message.setSessionId(request.getSessionId());
        message.setContent(request.getContent());
        messageService.addMessage(message);
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        System.out.println("[WebSocketAPI] 连接异常！" + exception.toString());
        UserEntity user = (UserEntity) session.getAttributes().get(ApplicationVariable.SESSION_USER_KEY);
        if(user == null) return;
        // 把这个webSocketSession从HashMap移除
        onlineUserManager.offline(user.getUser_id(),session);
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        System.out.println("[WebSocketAPI] 连接断开！" + status.toString());
        UserEntity user = (UserEntity) session.getAttributes().get(ApplicationVariable.SESSION_USER_KEY);
        if(user == null) return;
        // 把这个webSocketSession从HashMap移除
        onlineUserManager.offline(user.getUser_id(),session);
    }
}
